package com.lavender.extention.extention_interface;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.stereotype.Component;

/**
 * <p>
 * BeanDefinitionRegistryPostProcessor
 * 一：作用
 * BeanDefinitionRegistryPostProcessor接口继承自BeanFactoryPostProcessor接口，该处理器接口定义在spring-bean模块中，
 * 应用于ApplicationContext容器，即该处理器是为ApplicationContext容器扩展而被设计的，BeanFactoryPostProcessor处理器也
 * 是为扩展而设计的，但是不同的是BeanFactoryPostProcessor可以通过在BeanFactory手工设置该处理器来执行处理器方法，而
 * BeanDefinitionRegistryPostProcessor即使在BeanFactory中手工设置也无法被被调用，必须在ApplicationContext中才能被调用；
 * 该处理器方法的调用时间是在完成 BeanDefinition 注册后，实例化bean之前被调用的，该处理主要用于修改BeanDefinition注册元信息，
 * 它用于被ApplicationContext调用，在bean注册到ioc后创建实例前修改bean定义和新增bean注册，这个是在context的refresh
 * 方法调用。
 *
 * BeanDefinitionRegistryPostProcessor 的一个典型应用是扫描指定包及其子包下面拥有指定注解的类，你会发现在
 * BeanFactory中并没有使用到该后处理器，该后处理器为Spring容器扩展而设计的，IOC容器只加载一些常规的Bean配置，而像@Service、@Repository、@Compent和@Bean
 * 等这些注解定义的Bean是ApplicationContext容器中才扩展出来的，其中BeanDefinitionRegistryPostProcessor 有一个典型的应用是Mybatis中的@Mapper。
 * 此外，这里要注意的是@Service、@Repository、@Compent和@Bean这些注解修饰的Bean并不是通过后处理器来注入的，而是通过自定义命名空间解析器来注入的。
 *
 *
 * 二：使用场景
 * MapperScannerConfigurer：
 * 在mybatis集成spring的扩展包中（mybatis-spring-xxx.jar），就是通过MapperScannerConfigurer实现BeanDefinitionRegistryPostProcessor
 * 接口的postProcessBeanDefinitionRegistry方法来实现扫描@Mapper注解修饰的接口，并向BeanDefinition注册表中注册一系列的AnnotatedBeanDefinition对象，
 * 这样Spring就可以在后续的启动流程中向IOC容器注册Mapper接口对象实例了，从而实现Mybatis与Spring的集成。另外，Mybatis中的那些Mapper接口，会通过动态代理的方式生成一个接口的
 * 代理实例，从而完成一些持久化操作，这就是为什么Mybatis只需定义Mapper接口而不用实现类的原因；并且通过MapperScannerConfigurer
 * 注入的AnnotatedBeanDefinition对象，在实例化完成后其Bean对象是一个Mybatis的MapperFactoryBean对象，该MapperFactoryBean
 * 实现了Spring的FactoryBean接口，然后Spring容器在返回Mapper接口对象Bean的时候，就会通过FactoryBean接口来代理这个Mapper
 * 接口，该代理操作会委托Mybatis自己来完成。总之，Mybatis集成Spring中的Mapper接口，其本质是一个MapperFactoryBean，
 * MapperFactoryBean实现了FactoryBean，所以每个Mapper对象在实例化的时候会调用FactoryBean#getObject()方法，创建一个Mapper
 * 的实例。
 *
 * </p>
 * @author: zhu.chen
 * @date: 2020/12/22
 * @version: v1.0.0
 */
@Component
public class BeanDefinitionRegistryPostProcessorTest implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("BeanDefinitionRegistryPostProcessor postProcessBeanDefinitionRegistry");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("BeanDefinitionRegistryPostProcessor postProcessBeanFactory");
    }

}
